import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutterdemo/common/constants.dart';
import 'package:flutterdemo/utils/net_util.dart';
import 'package:flutterdemo/utils/sp_util.dart';

class HttpManager {
  static HttpManager _instance;

  factory HttpManager() => _getInstance();

  static HttpManager _getInstance() {
    if (_instance == null) {
      _instance = new HttpManager._();
    }
    return _instance;
  }

  HttpManager._() {
    dio = _createInstance();
  }

  /// global dio object
  Dio dio;
  static const int _CONNECT_TIMEOUT = 60000;
  static const int _RECEIVE_TIMEOUT = 60000;

  /// http request methods
  static const String _GET = 'get';
  static const String _POST = 'post';
  static const String _PUT = 'put';
  static const String _PATCH = 'patch';
  static const String _DELETE = 'delete';
  static const String _NETWORK_ERROR = '网络中断,请检查网络';
  String baseUrl = '';
  String tokenKey = '';

  get(
    String url,
    Map<String, dynamic> param,
    Function onSuccess,
    Function onError,
  ) async {
    _requestHttp(
      url,
      queryParameters: param,
      method: _GET,
      onSuccess: onSuccess,
      onError: onError,
    );
  }

  post(
    String url,
    param,
    Function onSuccess,
    Function onError,
  ) async {
    _requestHttp(
      url,
      data: param,
      method: _POST,
      onSuccess: onSuccess,
      onError: onError,
    );
  }

  /// T is Map<String,dynamic>  or List<dynamic>
  _requestHttp<T>(
    String url, {
    Map<String, dynamic> queryParameters,
    data,
    method,
    Function(T map) onSuccess,
    Function(String error) onError,
  }) async {
    if (await NetworkUtil.isNetworkAvailable() == false) {
      onError(_NETWORK_ERROR);
      return;
    }
    dio = _createInstance();
    try {
      Response response;
      response = await dio.request(
        url,
        queryParameters: queryParameters,
        data: data,
        options: new Options(method: method),
      );
      if (response.statusCode == HttpStatus.ok) {
        if (response.data == null || response.data == 'null') {
          onError("【返回数据null】");
        } else {
          onSuccess(json.decode(response.data));
        }
      } else {
        onError("【statusCode】${response.statusCode}");
      }
    } on DioError catch (e) {
      /// 打印请求失败相关信息
      print("【请求出错】${e.toString()}");
      onError(e.toString());
    }
  }

  /// 创建 dio 实例对象
  Dio _createInstance() {
    // if (dio == null) {
    /// 全局属性：请求前缀、连接超时时间、响应超时时间
    var options = new BaseOptions(
      // baseUrl: baseUrl,
      connectTimeout: _CONNECT_TIMEOUT,
      receiveTimeout: _RECEIVE_TIMEOUT,
      responseType: ResponseType.plain,
//        contentType: Headers.jsonContentType,
      headers: {
        "terminal": "Android",
        tokenKey: SpUtil().getString(Constants.token),
      },
    );
    dio = new Dio(options);
    dio.interceptors.add(new LogInterceptors());
    // }
    return dio;
  }

  /// 清空 dio 对象
  clear() {
    dio = null;
  }

  ///下载文件
  downloadFile(String urlPath, String savePath) async {
    var options = new BaseOptions(
      connectTimeout: _CONNECT_TIMEOUT,
      receiveTimeout: _RECEIVE_TIMEOUT,
    );
    dio = new Dio(options);
    dio.interceptors.add(new LogInterceptors());
    await dio.download(urlPath, savePath);
  }
}

///日志拦截器
class LogInterceptors extends InterceptorsWrapper {
  @override
  Future onRequest(RequestOptions options) {
    print("【请求url】${options.baseUrl}${options.path}");
//    print("【请求path】${options.path}");
    print("【请求headers】${options.headers.toString()}");
    print("【请求参数query】${options.queryParameters.toString()}");
    print("【请求参数data】${options.data.toString()}");
    return super.onRequest(options);
  }

  @override
  Future onResponse(Response response) {
    print("【返回statusCode】${response.statusCode}");
    print("【返回statusMessage】${response.statusMessage}");
    print("【返回headers】${response.headers.toString()}");
    print("【返回extra】${response.extra.toString()}");
    print("【返回data】${response.data.toString()}");
    return super.onResponse(response);
  }

  @override
  Future onError(DioError err) {
    print(err.toString());
    print(err.response?.toString());
    return super.onError(err);
  }
}
